Imports System.Data.SqlClient, System.Threading
Imports System.IO
Public Class Form1

#Region "Declaraciones"
    Private Socketz As New List(Of Winsock)
    Public Servidores As New List(Of Servidor)
    Public WithEvents MyTimer As New ThreadTimer
    Public WithEvents TimerCmdn As New ThreadTimer
    Public Elapsed As Date
    Public GotFirstTarget As Boolean = False
    Private Delegate Sub MostrarInfoEnTXT(ByVal msg As String, ByVal i As Integer, ByVal SrvNum As Integer)

    Private Conectado As Date
    Private Inside As Boolean = False
    Private SocketActual As Integer = 0

    Private SocketConectado As Boolean = False
    Public MiConexion As SqlConnection
    Public MiConString As String = "server=valp-maple01;uid=sa;pwd=messrv;database=WASP"
    'Public MiConString As String = "Data Source=video\SQLEXPRESS;Initial Catalog=WASP;Integrated Security=True"

    Public Structure Servidor
        Dim Ip As String
        Dim Puerto As Long
        Dim Number As String
        Dim CodigoOptima As String
        Dim Linea As String
    End Structure
#End Region

#Region "Sockets"

    Private Sub Sockets_Connectado(ByVal sender As Winsock)
        Try
            If sender.IsConected = True Then
                WaitSeconds(0.3)
                sender.Send(sender.CmdToSend)
                Log(sender.RemoteIP & " Connected, and sended the command  " & sender.CmdToSend)
            End If
            MostrarMsg("", 1, sender.Number)
            sender.LastGotData = Now
            If sender.CmdToSend = "I" Then
                MostrarMsg("", 5, sender.Number)
                sender.tstYellow = True
            End If
        Catch ex As Exception
            Log(ex.Message & "conectar", True)
        End Try
    End Sub

    Private Sub Sockets_Datos(ByVal sender As Winsock, ByVal BytesTotal As Integer)
        Try
            Dim bufferz As String = ""
            sender.GetData(bufferz)
            Dim Comando As String = ""
            Comando = bufferz.Substring(0, 1)
            '' MsgBox(bufferz, , Comando)
            If InStr(bufferz, "SORRY") > 0 Then Log(sender.RemoteIP & " got datas: " & vbCrLf & bufferz)

            Select Case Comando
                Case "I"

                    sender.LastGotData = Now
                    If sender.tstYellow = True Then
                        Dim Lns() As Object
                        Lns = bufferz.Split(vbCrLf)

       
                        Log(sender.RemoteIP & " Starting getting I " & vbCrLf & bufferz)


                        MostrarMsg("", 1, sender.Number)
                        sender.tstYellow = False
                    End If

                    Dim vars() As String = Nothing
                    Dim Tubo As String
                    Dim Letrita As String
                    Dim Peso As String
                    Dim Str As String

                    'For Each Linea As String In bufferz.Split(vbCrLf)
                    vars = bufferz.Split(",")
                    If vars.Length <> 4 Then Exit Sub
                    Comando = vars(0)
                    Tubo = vars(1)
                    Letrita = vars(2)
                    Peso = vars(3).Trim
                    Str = Tubo & "," & Peso & "," & sender.CodOptima
                    MostrarMsg(Str, 3, sender.Number)
                    'Next

                Case "N"
                    Dim Lineas() As Object
                    Lineas = bufferz.Split(vbCrLf)

                    If Not Lineas.Length > 2 Then
                        'raise the error
                        'MsgBox(bufferz, , "nope")
                        Exit Sub
                    End If
                    If GotFirstTarget = False Then
                        Elapsed = Now
                        Me.TimerCmdn.StartTimer()
                        GotFirstTarget = True
                    End If

                    Dim MiLinea As String
                    MiLinea = Lineas(2)
                    Dim Marca As String = ""
                    Dim Target As Double
                    Dim Secciones() As Object

                    Dim Indicador As Integer

                    For Each Linea As String In Lineas
                        Secciones = Linea.Split(",")
                        If Secciones.Length <= 3 Then Continue For
                        Indicador = Val(Secciones(2))

                        Select Case Indicador
                            Case 500 'Marca
                                Marca = Secciones(3)
                            Case 2500
                                Target = Val(Secciones(3))
                                sender.GotTarget = True
                        End Select
                    Next
                    If Marca = "" Or Target = 0 Then Exit Sub
                    sender.CmdToSend = "I"
                    sender.SendingN = False
                    Dim str = sender.CodOptima & "," & Target & "," & Marca
                    MostrarMsg(str, 2, sender.Number)
                    'MostrarMsg(Marca & "," & Target, 1, sender.Number)

                    sender.Close()

                    'n,0,500,ARIEL     MB  
                    'n,0,500,ACE     MB
                Case Else
                    Log(sender.RemoteIP & " got data: " & vbCrLf & bufferz)
            End Select
        Catch ex As Exception
            Log(sender.RemoteIP & "Error al recibir datos: " & ex.Message, True)
        End Try
    End Sub

    Private Sub Sockets_Desconectado(ByVal sender As Winsock)
        MostrarMsg(sender.RemoteIP & ":" & sender.RemotePort & " Desconectado", 2)
        MostrarMsg("", 4, sender.Number)
        Log(sender.RemoteIP & "Disconected: ")

        If sender.CmdToSend = "I" Then
            System.Threading.Thread.Sleep(500)
            sender.Connect()
        End If

    End Sub

    Private Sub Socket_HandleError(ByVal Sender As Winsock, ByVal Description As String, ByVal Method As String, ByVal myEx As String)
        'MsgBox(Sender.RemoteIP, , Ex.Message)
        If myEx = "Could not connect" Or myEx = "Could not resolve Host name or Address." Then
            MostrarMsg(Sender.RemoteIP & ":" & Sender.RemotePort & " Caido", 2)
            MostrarMsg("", 4, Sender.Number)
        End If

        Log(Sender.RemoteIP & " Error: " & myEx & ":" & Method, True)
    End Sub

#End Region

#Region "Funciones y Procedimientos"

    Sub Iniciar()
        TimerCmdn = New ThreadTimer(10000, -1)
        MyTimer = New ThreadTimer(30000, -1)
        For Each Server As Servidor In Servidores
            Socketz.Add(New Winsock(Server.Ip, Server.Puerto))
            Socketz.Item(Socketz.Count - 1).Number = Server.Number
            Socketz.Item(Socketz.Count - 1).CodOptima = Server.CodigoOptima
            Socketz.Item(Socketz.Count - 1).CmdToSend = "N" 'Al iniciar enviar el comando n
            Socketz.Item(Socketz.Count - 1).SendingN = False
            Socketz.Item(Socketz.Count - 1).Linea = Server.Linea
            AddHandler Socketz.Item(Socketz.Count - 1).Connected, AddressOf Sockets_Connectado
            AddHandler Socketz.Item(Socketz.Count - 1).DataArrival, AddressOf Sockets_Datos
            AddHandler Socketz.Item(Socketz.Count - 1).HandleError, AddressOf Socket_HandleError
            AddHandler Socketz.Item(Socketz.Count - 1).Disconnected, AddressOf Sockets_Desconectado
            SocketActual += 1
        Next
        HazTodo()
    End Sub

    ''' <summary>
    ''' Procedimiento que toma los servidores desde sql server
    ''' y los agrega a la lista Servidores
    ''' </summary>
    ''' <remarks></remarks>
    Sub CargarServers()
        Servidores.Clear()
        MiConexion = New SqlConnection(Me.MiConString)
        Dim MiComando As New SqlCommand("Select ip,port,codigo,Linea from Optimas", MiConexion)
        Dim MyReader As SqlDataReader

        Try
            Application.DoEvents()
            MiConexion.Open()
            Application.DoEvents()
            MyReader = MiComando.ExecuteReader()

            While MyReader.Read()
                'reading from the datareader
                Dim Servidor As New Servidor
                Servidor.Ip = MyReader(0).ToString
                Servidor.Puerto = Val(MyReader(1).ToString)
                Servidor.CodigoOptima = MyReader(2).ToString
                Servidor.Number = Servidores.Count + 1
                Servidor.Linea = MyReader(3).ToString
                If Servidor.Puerto = 0 Then Continue While
                Servidores.Add(Servidor)

            End While
            MyReader.Close()
            MiConexion.Close()
            CargarSevrersEnListBox()
        Catch e As Exception
            'MsgBox(e.Message)
        End Try
    End Sub

    ''' <summary>
    ''' Muestra los servidores en el listBox lstServidores
    ''' </summary>
    ''' <remarks></remarks>
    Sub CargarSevrersEnListBox()
        lstServidores.Items.Clear()
        For Each Server As Servidor In Servidores
            Dim NewItem As New ListViewItem
            NewItem = lstServidores.Items.Add(Server.Ip)
            NewItem.BackColor = Color.Red
            NewItem.ForeColor = Color.White
            NewItem.SubItems.Add(Server.Puerto)
            NewItem.SubItems.Add(0)
            NewItem.SubItems.Add("null")
            NewItem.SubItems.Add(Server.Linea)
        Next
        Me.Refresh()
    End Sub

    ''' <summary>
    ''' Inserta los pesos en sql server
    ''' </summary>
    ''' <param name="vaso"></param>
    ''' <param name="peso"></param>
    ''' <param name="codigo"></param>
    ''' <remarks></remarks>
    <STAThread()> _
    Sub InsertarDatos(ByVal vaso As String, ByVal peso As String, ByVal codigo As String)
        MiConexion = New SqlConnection(Me.MiConString)
        Dim cmd As String = "INSERT INTO pesos(Peso,vaso,codOptima,Fecha,Hora) " & _
        "VALUES(_peso, _vaso, _codOptima, _fecha,'_hora')"
        Dim f As Date = Now
        Dim Hour As Integer = Now.Hour
        Dim Minute As Integer = Now.Minute
        Dim Hora As String = ""

        If Minute <= 30 Then
            Hora = Hour & ":00" & " - " & Hour & ":30"
        Else
            Hora = Hour & ":30" & " - " & (Hour + 1) & ":00"
        End If
        cmd = cmd.Replace("_hora", Hora)
        cmd = cmd.Replace("_peso", peso)
        cmd = cmd.Replace("_vaso", vaso)
        cmd = cmd.Replace("_codOptima", "'" & codigo & "'")
        cmd = cmd.Replace("_fecha", "CAST('" & Format(Now, "yyyy-MM-dd HH:mm:ss") & "' AS datetime)")
        'MsgBox(cmd) 'CAST('20070529 00:00:00' AS datetime)
        'If 1 Then Exit Sub

        Dim MiComando As New SqlCommand(cmd, MiConexion)
        Try
            MiConexion.Open()
            MiComando.ExecuteNonQuery()
            MiConexion.Close()
        Catch ex As Exception
            Log("Error al insertar el peso " & ex.Message)
            MiConexion.Close()
        End Try
    End Sub

    Sub GuardaTarget(ByVal codigo As String, ByVal target As Double, ByVal marca As String)
        MiConexion = New SqlConnection(Me.MiConString)


        Dim Hour As Integer = Now.Hour
        Dim Minute As Integer = Now.Minute
        Dim Hora As String = ""

        If Minute <= 30 Then
            Hora = Hour & ":00" & " - " & Hour & ":30"
        Else
            Hora = Hour & ":30" & " - " & (Hour + 1) & ":00"
        End If

        Dim cmd As String = "storeTarget '_cod',_tar,'_mar', _fe, '_hora'"
        cmd = cmd.Replace("_hora", Hora)
        cmd = cmd.Replace("_cod", codigo)
        cmd = cmd.Replace("_tar", target)
        cmd = cmd.Replace("_mar", marca)
        cmd = cmd.Replace("_fe", "'" & Format(Now, "yyyy-MM-dd HH:mm:ss") & "'")

        Dim MiComando As New SqlCommand(cmd, MiConexion)
        Try
            MiConexion.Open()
            MiComando.ExecuteNonQuery()
            MiConexion.Close()
            LOg("se guardo el target:" & codigo & "," & target & "," & marca)
        Catch ex As Exception
            MiConexion.Close()
            cmd = cmd
            Log("Error al tratar de guardar el target:" & codigo & "," & target & "," & marca)
        End Try
    End Sub

    ''' <summary>
    ''' Procedimiento para acceder a los controles del formulario desde otros procesos
    ''' </summary>
    ''' <param name="msg">El mensaje a establecer</param>
    ''' <param name="i">Numero de Opcion</param>
    ''' <param name="SrvNum">numero de servidor</param>
    ''' <remarks></remarks>
    Sub MostrarMsg(Optional ByVal msg As String = "", Optional ByVal i As Integer = 0, Optional ByVal SrvNum As Integer = 0)
        If Me.InvokeRequired Then
            Dim EnviarMsg As New MostrarInfoEnTXT(AddressOf MostrarMsg)
            Dim Parametros(2) As Object
            Parametros(0) = msg
            Parametros(1) = i
            Parametros(2) = SrvNum

            Me.Invoke(EnviarMsg, Parametros)
        Else
            Try
                Dim msgnew As String = msg & vbCrLf
                Select Case i
                    Case 1
                        If Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Green Then Exit Sub
                        Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Green
                        Me.lstServidores.Items(SrvNum - 1).ForeColor = Color.Gold
                        Me.Refresh()
                    Case 2
                        Dim str() As Object = msg.Split(",")
                        If str.Length <> 3 Then Exit Sub
                        Dim Cod As String = str(0)
                        Dim Tar As Double = str(1)
                        Dim Mar As String = str(2)
                        lstServidores.Items(SrvNum - 1).SubItems(2).Text = Tar
                        lstServidores.Items(SrvNum - 1).SubItems(3).Text = Mar
                        Me.Refresh()
                        'NewItem.SubItems.Add("Desconectado")
                        GuardaTarget(Cod, Tar, Mar)
                    Case 3
                        'Me.txtData.Clear()
                        Dim str() As Object = msg.Split(",")
                        Dim tubo As String = str(0)
                        Dim peso As String = str(1)
                        Dim codigo As String = str(2)
                        If Not str.Length = 3 Then
                            Exit Sub
                        End If

                        Me.InsertarDatos(tubo, peso, codigo)
                    Case 4
                        If Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Red Then Exit Sub
                        Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Red
                        Me.lstServidores.Items(SrvNum - 1).ForeColor = Color.White
                    Case 5
                        If Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Yellow Then Exit Sub
                        Me.lstServidores.Items(SrvNum - 1).BackColor = Color.Yellow
                        Me.lstServidores.Items(SrvNum - 1).ForeColor = Color.Green
                End Select
            Catch ex As Exception
                Log("Error al mostrarMsg " & ex.Message, True)
            End Try
        End If
    End Sub

    Sub DesconectarTodos()
        Try
            For Each Sck As Winsock In Socketz
                If Sck.IsConected Then
                    Sck.Send("X")
                End If
                Sck.Close()
            Next
        Catch ex As Exception

        End Try
    End Sub

    Sub ConectayEnvia(ByVal Comando As String)
        Try
            For Each Sck As Winsock In Socketz
                Sck.CmdToSend = Comando
                Sck.Connect()
            Next
        Catch ex As Exception

        End Try
    End Sub

    Sub HazTodo()
        Try
            MyTimer.StopTimer()
            GotFirstTarget = False
            Log("Iniciando Haz todo")
            Try
                For Each Sck As Winsock In Socketz
                    If Sck.GetState = Winsock.WinsockStates.Connected Then
                        Sck.Send("X")
                        Application.DoEvents()
                        Thread.Sleep(500)
                    End If
                    Sck.CmdToSend = "N"
                    Sck.Close()
                Next
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
            WaitSeconds(0.5)
            Log("Sockets Cerrados")
            For Each Sck As Winsock In Socketz
                Sck.CmdToSend = "N"
                Sck.Connect()
            Next
            Log("Se mando N")

            'For Each Sck As Winsock In Socketz
            '    Sck.CmdToSend = "I"
            '    Sck.Connect()
            'Next
            'Log("Se mando I")
            WaitSeconds(60)

            MyTimer.StartTimer()

        Catch ex As Exception
            Log(ex.Message & " Haztodo")
        End Try
    End Sub

    Sub GetAllConnected()
        Dim Str As String = ""
        For Each Item As ListViewItem In lstServidores.Items
            If Item.BackColor <> Color.Green Then Continue For
            For Each SubItem As ListViewItem.ListViewSubItem In Item.SubItems
                Str &= SubItem.Text & " "
            Next
            Str &= vbCrLf
        Next
        If Str = "" Then Exit Sub
        My.Computer.Clipboard.SetText(Str)
    End Sub

    Private Sub WaitSeconds(ByVal nSecs As Double)
        Dim t1 As DateTime = DateTime.Now.AddSeconds(nSecs)
        Dim t2 As DateTime = DateTime.Now

        Do While t2 < t1
            System.Windows.Forms.Application.DoEvents()
            t2 = DateTime.Now
        Loop
    End Sub

    Sub Log(ByVal msg As String, Optional ByVal IsError As Boolean = False)
        Try
            Dim File As String
            If IsError = True Then
                If InStr(msg, "actively refused") > 0 Then Exit Sub
                If InStr(msg, "properly respond") > 0 Then Exit Sub
                'If InStr(msg, "actively refused") > 0 Then Exit Sub
                File = Application.StartupPath & "\logerr.txt"
            Else
                File = Application.StartupPath & "\log.txt"
            End If
            Dim fs As New FileStream(File, FileMode.Append, FileAccess.Write)

            Dim s As New StreamWriter(fs)

            s.BaseStream.Seek(0, SeekOrigin.End)
            s.WriteLine(Now.ToString)
            s.WriteLine(msg)
            'writing text to the newly created file
            s.Close()
        Catch ex As Exception

        End Try
    End Sub
#End Region

#Region "Timers"

    Private Sub MyTimer_OnExecute() Handles MyTimer.OnExecute
        For Each Server As Winsock In Socketz
            If Server Is Nothing Then
                'Log(Server.RemoteIP & ": Reconectando Obj=Nothing (Mytimer) " & Server.CmdToSend)
                Server.Close()
                WaitSeconds(0.5)
                Server.Connect()
                Log("Reconectando " & Server.CmdToSend)
                Continue For
            End If
            If Server.IsConected = False Then
                'Log(Server.RemoteIP & ": Reconectando Obj=Disc (Mytimer) " & Server.CmdToSend)
                Server.Close()
                WaitSeconds(0.5)
                Server.Connect()
            End If

        Next
        'Catch ex As Exception
        '    Log("Error en el timer:" & ex.Message, True)
        'End Try
    End Sub

    Private Sub TimerCmdn_OnExecute() Handles TimerCmdn.OnExecute
        Try
            Dim minutes As Integer
            minutes = DateAndTime.DateDiff(DateInterval.Minute, Elapsed, Now)

            'Si aun no pasan los 30 minutos salirse del procedimiento
            If minutes < 30 Then Exit Sub

            Elapsed = Now 'actualizar la hora para que espere otros 30 minutos =)
            Log("Ok Obteniendo de nuevo los targets (TimerCmdN) ")
            HazTodo()
        Catch ex As Exception
            MsgBox("Que pedo")
            Log("Error en el timer: " & ex.Message, True)
        End Try
    End Sub
#End Region

#Region "Eventos Controles"
    Private Sub MyNotifyIcon_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyNotifyIcon.MouseDoubleClick
        Me.Visible = Not Me.Visible
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        CargarServers()
    End Sub
    Dim NuevoProceso As Thread
    Private Sub btniniciar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btniniciar.Click
        NuevoProceso = New Thread(AddressOf Iniciar)
        NuevoProceso.Name = "Iniciar"

        NuevoProceso.Start()
        btniniciar.Text = "Iniciado"
    End Sub

    Private Sub lstServidores_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstServidores.DoubleClick
        Try
            Me.GetAllConnected()
            Dim sck As Winsock
            sck = Me.Socketz.Item(lstServidores.SelectedIndices.Item(0))
            MsgBox(sck.IsConected, , sck.remoteip & " GotTarget:" & sck.GotTarget)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim File As String = Application.StartupPath & "\log.txt"
        Dim File2 = Application.StartupPath & "\logerr.txt"
        Try
            If System.IO.File.Exists(file) = True Then
                System.IO.File.Delete(file)
            End If
            If System.IO.File.Exists(File2) = True Then
                System.IO.File.Delete(File2)
            End If
        Catch ex As Exception

        End Try

    End Sub

   
    
#End Region


End Class
